{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6996a2c78dba"
   },
   "source": [
    "# Getting Started with IonQ and Cirq"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "f4af1602b1e6"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://quantumai.google/cirq/hardware/ionq/getting_started\"><img src=\"https://quantumai.google/site-assets/images/buttons/quantumai_logo_1x.png\" />View on QuantumAI</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/quantumlib/Cirq/blob/main/docs/hardware/ionq/getting_started.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/colab_logo_1x.png\" />Run in Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq/blob/main/docs/hardware/ionq/getting_started.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/github_logo_1x.png\" />View source on GitHub</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a href=\"https://storage.googleapis.com/tensorflow_docs/Cirq/docs/hardware/ionq/getting_started.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/download_icon_1x.png\" />Download notebook</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "34625186c8a4"
   },
   "source": [
    "This notebook shows how to get up and running with the IonQ API.  As of February 2021, this API is limited to partners only. More information about partnerships can be found at [ionq.com/get-started](https://ionq.com/get-started).\n",
    "\n",
    "To get started, first you must install Cirq. \n",
    "\n",
    "> NOTE: Currently this notebook requires the version of Cirq 0.10 or higher."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "f5008c9c33b4"
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    import cirq\n",
    "\n",
    "    version = cirq.__version__.split(\".\")\n",
    "    assert int(version[0]) > 0 or int(version[1]) > 9, \"Cirq version >0.9 required\"\n",
    "except (ImportError, AssertionError):\n",
    "    print(\"Installing Cirq...\")\n",
    "    !pip install --quiet cirq\n",
    "    print(\"Cirq installed.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1bdedbe68161"
   },
   "source": [
    "Given that the above cell runs, you have installed Cirq and imported it.  To simplify using the ionq api it is also suggested that you import ionq. Notice how nice it is that cirq and ionq are four letter words ending in \"q\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "22bc38124ede"
   },
   "outputs": [],
   "source": [
    "import cirq\n",
    "import cirq_ionq as ionq"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "81d55416de71"
   },
   "source": [
    "## Constructing an IonQ Service object"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "11b21e6193ae"
   },
   "source": [
    "The main object that you use to access the IonQ API is an instance of the `cirq_ionq.Service` class.  To construct this you need an API key. Both should be supplied to partners. Please be careful when using notebooks and version control to not save your API key in a public location!\n",
    "\n",
    "Given these bits of information you get a service object by simply running"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "id": "800002580d0d"
   },
   "outputs": [],
   "source": [
    "API_KEY = 'tomyheart'  # Replace with your IonQ API key\n",
    "\n",
    "service = ionq.Service(api_key=API_KEY, default_target='simulator')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "042b4395ec4e"
   },
   "source": [
    "Note that we have set the `default_target` to `simulator`.  The other option would be to set it to `qpu`.\n",
    "\n",
    "## Running a simple circuit\n",
    "\n",
    "The IonQ API supports a limited set of gates natively.  Circuit built with these gates do not need any modification and can be run directly against the API.  For a list of the API supported gates see [circuit documentation](./circuits.md).  One supported gate is the square root of not gate, which we use here in conjunction with a controlled-not gate. The following cell will run the circuit below, blocking until the program has run and results have been returned:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "id": "1ffa7a842d3c"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b=0100110001000110100000000110101111100110100001110110111010010011001011001100001001100110100011001111, 0100110001000110100000000110101111100110100001110110111010010011001011001100001001100110100011001111\n"
     ]
    }
   ],
   "source": [
    "q0, q1 = cirq.LineQubit.range(2)\n",
    "circuit = cirq.Circuit(\n",
    "    cirq.X(q0) ** 0.5,  # Square root of X\n",
    "    cirq.CX(q0, q1),  # CNOT\n",
    "    cirq.measure(q0, q1, key='b'),  # Measure both qubits\n",
    ")\n",
    "result = service.run(circuit, repetitions=100)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "d5d62daa9d1e"
   },
   "source": [
    "Because we did not specify a `target` and we ran this against a service with `default_target='simulator'`, this ran against the simulator. To run against the QPU simply add the target to the `run` method (note that this may take a while since the queue for the qpu is much longer than that for the simulator):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "id": "019fdd573787"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b=1101101100001000011111111011110001111011100011101001000110000001001001011100111001000110000110111110, 1101101100001000011111111011110001111011100011101001000110000001001001011100111001000110000110111110\n"
     ]
    }
   ],
   "source": [
    "result = service.run(circuit, repetitions=100, target='qpu')\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6f18ed2cc703"
   },
   "source": [
    "## Jobs\n",
    "\n",
    "In the above section, the `run` method blocked on awaiting the program to run and return results. A different pattern is to asynchronously create jobs, which return an id that they can be used to identify the job, and fetch the results at a later time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "id": "7353114a3b17"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Job id: 34be7d9b-1a27-4974-b8ca-2b5941e52cd8\n"
     ]
    }
   ],
   "source": [
    "job = service.create_job(circuit, repetitions=100)\n",
    "job_id = job.job_id()\n",
    "print(f'Job id: {job_id}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "68dea73d380c"
   },
   "source": [
    "Given the `job` object above, you can check on the status of the job"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "id": "9b24b14182c9"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Status: completed\n"
     ]
    }
   ],
   "source": [
    "print(f'Status: {job.status()}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8ac6188f9053"
   },
   "source": [
    "Or if you only have the job id, you can use this to get the job and create a new `cirq_ionq.Job` object to query."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "id": "a3b60c874b76"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Status: completed\n"
     ]
    }
   ],
   "source": [
    "same_job = service.get_job(job_id=job_id)\n",
    "print(f'Status: {same_job.status()}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "9c18cf2b3e62"
   },
   "source": [
    "To get the results from the job, you can get the results of the job using the `results()` method.  Note, however that this will block if the job is not completed, polling until the status is `completed`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "id": "61ea7a4d3287"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "00: 0.5000000000000001\n",
      "11: 0.4999999999999999\n"
     ]
    }
   ],
   "source": [
    "results = same_job.results()\n",
    "print(results)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2583244eef7f"
   },
   "source": [
    "Note that the results are not `cirq.Result`. To convert these to a `cirq.Result`, you can use `to_cirq_result()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "id": "5051f3116d52"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b=0100001001111001110001111100101001010100010011100101011000111100110101100000110010110010001101111101, 0100001001111001110001111100101001010100010011100101011000111100110101100000110010110010001101111101\n"
     ]
    }
   ],
   "source": [
    "print(results.to_cirq_result())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "9cc9d9b62c2d"
   },
   "source": [
    "## Next steps\n",
    "\n",
    "Check out the documentation on fully using the Cirq IonQ integration\n",
    "\n",
    "[Learn how to build circuits for the API](./circuits.md)\n",
    "\n",
    "[How to use the service API](./jobs.md)\n",
    "\n",
    "[Learn how to query the performance of a processor by accessing IonQ calibrations](./calibrations.md)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "getting_started.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
